package org.zjt.algorithm;

import joptsimple.internal.Strings;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.*;

/**
 * CountDownLatch、CyclicBarrier 区别：
 *      1、都是等到n个condition后才会继续执行。
 *      2、CountDownLatch 只能使用一次，CyclicBarrier自动可以循环使用。
 *      3、CopyOnWrite：适合读多写少。
 *
 * Concurrent*、CopyOnWrite和 Blocking等三类。
 *      1、Concurrent支持并发，内部多用cas或者AQS同步的方式。
 *      2、CopyOnWrite支持并发，多用于读多写少的场景，写入资源开销大。
 *      3、Blocking支持并发，多使用线程阻塞的方式同步。
 *      4、队列是否有长度限制。
 *
 * fail-fast:直接在容器上进行遍历，在遍历过程中，一旦发现容器中的数据被修改了，会立刻抛出ConcurrentModificationException异常导致遍历失败。
 *          java.util包下的集合类都是快速失败机制的, 常见的的使用fail-fast方式遍历的容器有HashMap和ArrayList等。
 *
 *
 *          多线程：必须使用并发容器，否则会抛出ConcurrentModificationException。
 *          单线程：可以利用迭代器方式。
 *
 *
 * fail-safe:这种遍历基于容器的一个克隆，使用迭代器操作（增、删、改）。因此，对容器内容的修改不影响遍历。java.util.concurrent包下的容器都是安全失败的,
 *          可以在多线程下并发使用,并发修改。常见的的使用fail-safe方式遍历的容器有ConcurrentHashMap和CopyOnWriteArrayList等。
 *
 *
 * https://blog.csdn.net/striner/article/details/86375684
 *
 *
 */
public class JUCTest {


    public static void main(String[] args) {
        Map<String,Integer> data = new ConcurrentHashMap<>();
        new Thread(() -> {
            for (int i = 0;i < 10000;i ++){
                data.put(String.valueOf(i),i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();


        new Thread(() -> {
            for (int i = 0;i < 10000;i ++){
                Iterator<Map.Entry<String, Integer>> iterator = data.entrySet().iterator();
                while (iterator.hasNext()){
                    Map.Entry<String, Integer> item = iterator.next();
                    System.out.println(item.getKey() + " , " + item.getValue());
                }

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }).start();

    }

    public static void TestCyclicBarrier(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
        for (int i = 0 ;i < 12;i ++){
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    cyclicBarrier.await();
                    System.out.println("---------------------");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        System.out.println(cyclicBarrier.getNumberWaiting());
    }

    public static void TestCountDownLatch(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(4);
        for (int i = 0 ;i < 4;i ++){
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("-------------------");

    }
}
